{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# Using `mayavi.mlab`: Animation\n",
    "\n",
    "**Prabhu Ramachandran**\n",
    "\n",
    "**Department of Aerospace Engineering, IIT Bombay**\n",
    "\n",
    "<br/>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Outline\n",
    "\n",
    "- Getting started with `mlab`\n",
    "- Using `mlab`\n",
    "   - The basics\n",
    "   - **Animation** $\\Longleftarrow$\n",
    "- Going deeper\n",
    "   - The pipeline\n",
    "   - Data sources\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [],
   "source": [
    "%gui qt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from mayavi import mlab"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Animation\n",
    "\n",
    "* Specific to `mlab`\n",
    "* `points3d, plot3d, surf, mesh`, `quiver3d, contour3d` etc.\n",
    "* Returned object has `mlab_source` attribute\n",
    "* Setting attributes updates the plot\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Animating data\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "mlab.clf()\n",
    "x, y = np.mgrid[0:3:1,0:3:1]\n",
    "s = mlab.surf(x, y, x*0.1)\n",
    "for i in range(10):\n",
    "    s.mlab_source.scalars = x*0.1*(i+1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## But did it really animate??\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import time\n",
    "mlab.clf()\n",
    "x, y = np.mgrid[0:3:1,0:3:1]\n",
    "s = mlab.surf(x, y, x*0.1)\n",
    "for i in range(10):\n",
    "    s.mlab_source.scalars = x*0.1*(i+1)\n",
    "    time.sleep(0.1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [],
   "source": [
    "mlab.clf()\n",
    "x, y = np.mgrid[0:3:1,0:3:1]\n",
    "s = mlab.surf(x, y, x*0.1)\n",
    "for i in range(10):\n",
    "    s.mlab_source.scalars = x*0.1*(i+1)\n",
    "    mlab.savefig('/tmp/anim_%02d.png' % i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [],
   "source": [
    "mlab.clf()\n",
    "x, y = np.mgrid[0:3:1,0:3:1]\n",
    "s = mlab.surf(x, y, x*0.1)\n",
    "for i in range(10):\n",
    "    s.mlab_source.scalars = x*0.1*(i+1)\n",
    "    mlab.process_ui_events()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Animation: `mlab_source.set`\n",
    "Use `mlab_source.set` to change multiple values\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for i in range(10):\n",
    "    s.mlab_source.set(\n",
    "        scalars=x*0.1*(i+1), y=y+i*0.5\n",
    "    )\n",
    "    mlab.process_ui_events()\n",
    "    time.sleep(0.1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Animation: `mlab_source.reset`\n",
    "\n",
    "Use reset if shape changes\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "mlab.clf()\n",
    "x, y = np.mgrid[0:3:1,0:3:1]\n",
    "s = mlab.surf(x, y, x*0.1, representation='wireframe')\n",
    "\n",
    "fig = mlab.gcf()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for i in range(5):\n",
    "  sl = slice(0, 3, 1.0/(i+2))\n",
    "  x, y = np.mgrid[sl, sl]\n",
    "  sc = x*x*0.05*(i+1)\n",
    "  s.mlab_source.reset(x=x, y=y, scalars=sc)\n",
    "  fig.scene.reset_zoom()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## `set` vs `reset`\n",
    "\n",
    "* `mlab_source.set`: multiple attributes\n",
    "\n",
    "* If you change the shape of the arrays use the\n",
    "  `reset` method\n",
    "\n",
    "* See `mlab.test_*_anim`  functions for more examples!\n",
    "\n",
    "* Use `mlab.savefig` : to dump files\n",
    "\n",
    "* `savefig`  supports a variety of output\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Finding the traits you can change\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "s.mlab_source.print_traits()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Animate decorator\n",
    "\n",
    "* `mlab.animate`\n",
    "* Useful when interactivity is desired\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "@mlab.animate\n",
    "def anim():\n",
    "    x, y = np.mgrid[0:3:1,0:3:1]\n",
    "    s = mlab.surf(x, y, x*0.1)\n",
    "    for i in range(25):\n",
    "        s.mlab_source.set(\n",
    "            scalars = x*0.1*(i+1))\n",
    "        yield"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = anim()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Notes\n",
    "\n",
    "* Only works with a generator\n",
    "\n",
    "* Note that the UI is fully interactive\n",
    "\n",
    "* Can adjust the delay\n",
    "\n",
    "Can also do,\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "@mlab.animate(delay=100, ui=False)\n",
    "def anim():\n",
    "    x, y = np.mgrid[0:3:1,0:3:1]\n",
    "    s = mlab.surf(x, y, x*0.1)\n",
    "    for i in range(25):\n",
    "        s.mlab_source.set(\n",
    "            scalars = x*0.1*(i+1))\n",
    "        yield"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Exercise\n",
    "\n",
    "Create a stack of images animating the example below such that it looks\n",
    "like the wave is moving.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x, y = np.mgrid[-3:3:100j,-3:3:100j]\n",
    "z = np.sin(x*x + y*y)\n",
    "s = mlab.surf(x, y, z)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Solution\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Your solution here!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%load solutions/03_wave_anim.py"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Automatic movie recording\n",
    "\n",
    "* Click on \"record\" on the scene movie tab\n",
    "\n",
    "* Or try the following\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "f = mlab.figure()\n",
    "f.scene.movie_maker.record = True\n",
    "mlab.test_mesh_sphere_anim()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## What next?\n",
    "\n",
    "- Going deeper!\n"
   ]
  }
 ],
 "metadata": {
  "celltoolbar": "Slideshow",
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.0"
  },
  "livereveal": {
   "controls": true,
   "help": true,
   "scroll": true,
   "slideNumber": true,
   "transition": "none"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
